// Copyright (c) 2012, yuno. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
//    this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
package sugarmintcandy.widgetwindow;

import java.util.Arrays;
import java.util.Random;

import android.content.Context;
import android.graphics.Color;
import android.util.DisplayMetrics;
import android.util.FloatMath;
import android.view.Display;
import android.view.WindowManager;

public final class Utilities {
    private static final Random sRandom = new Random();

    private Utilities() {
    }

    public static int randomInt(int n) {
	return sRandom.nextInt(n);
    }

    public static float randomFloat() {
	return sRandom.nextFloat();
    }

    public static long randomLong() {
	return sRandom.nextLong();
    }

    public static int randomColor(MainDatabase db) {
	float[] hsv = new float[3];
	int[] colors = db.getRecentColors();
	if (colors.length == 0) {
	    hsv[0] = randomFloat() * 360;
	} else {
	    int n = colors.length;
	    float[] hues = new float[n + 1];
	    for (int i = 0; i < n; i++) {
		Color.colorToHSV(colors[i], hsv);
		hues[i] = hsv[0];
	    }
	    hues[n] = Float.POSITIVE_INFINITY;
	    Arrays.sort(hues);
	    hues[n] = hues[0] + 360;
	    Debug.trace("hues=%s", hues);
	    float maxDistance = Float.NEGATIVE_INFINITY;
	    float maxHue = 0;
	    for (int i = 0; i < n; i++) {
		float h0 = hues[i];
		float h1 = hues[i + 1];
		float dist = h1 - h0;
		if (maxDistance < dist) {
		    maxDistance = dist;
		    maxHue = (h0 + h1) / 2f;
		}
	    }
	    if (maxHue >= 360) {
		maxHue -= 360;
	    }
	    hsv[0] = maxHue;
	    Debug.trace("result=%f, distance=%f", maxHue, maxDistance);
	}
	hsv[1] = FloatMath.sqrt(randomFloat()) / 2f + 0.5f;
	hsv[2] = FloatMath.sqrt(randomFloat()) / 2f + 0.5f;
	return Color.HSVToColor(hsv);
    }

    private static final byte[] base64DecodeTable;
    static {
	byte[] b = new byte[128];
	Arrays.fill(b, (byte) -1);
	String s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	for (int i = 0; i < 64; i++) {
	    b[s.charAt(i)] = (byte) i;
	}
	base64DecodeTable = b;
    }

    public static byte[] decodeBase64(String s) {
	int len = s.length();
	if (s.endsWith("==")) {
	    len -= 2;
	} else if (s.endsWith("=")) {
	    len--;
	}
	int n = len * 3 / 4;
	byte[] b = new byte[n];
	for (int i = 0, j = 0; i < n;) {
	    int x = 0;
	    for (int k = 18; k >= 0 && j < len; k -= 6, j++) {
		char c = s.charAt(j);
		int d = base64DecodeTable[c];
		x |= d << k;
	    }
	    if (x < 0) {
		throw new IllegalArgumentException();
	    }
	    for (int k = 16; k >= 0 && i < n; k -= 8, i++) {
		b[i] = (byte) (x >> k);
	    }
	}
	return b;
    }

    public static DisplayMetrics getDisplayMetrics(Context context) {
	WindowManager wm = (WindowManager) context
		.getSystemService(Context.WINDOW_SERVICE);
	return getDisplayMetrics(wm);
    }

    public static DisplayMetrics getDisplayMetrics(WindowManager wm) {
	DisplayMetrics dm = new DisplayMetrics();
	getDisplayMetrics(wm, dm);
	return dm;
    }

    public static void getDisplayMetrics(WindowManager wm, DisplayMetrics dm) {
	Display display = wm.getDefaultDisplay();
	display.getMetrics(dm);
	dm.heightPixels = ApiHelper.getRawHeight(display);
    }
}
